package com.witmore.neutron.ai.web.apiv2.filter;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jk.common.enums.WitmoreErrorCode;
import com.jk.common.exception.WitmoreException;
import com.jk.common.response.ResponseResult;
import com.jk.common.utils.JwtUtil;
import com.witmore.neutron.ai.db.entity.UserDO;
import com.witmore.neutron.ai.db.mapper.UserMapper;
import com.witmore.neutron.ai.web.annotation.NoLoginRequired;
import com.witmore.neutron.ai.web.annotation.RequiresPermission;
import com.witmore.neutron.ai.web.controller.vo.UserSession;
import com.witmore.neutron.ai.web.filter.GlobalAccountSession;
import com.witmore.neutron.ai.web.service.PermissionService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.util.List;


/**
 * API V2接口专用的Token认证拦截器
 * 用于处理纯后端API接口的鉴权，基于Header中的Authorization token
 *
 * @author 豆子高
 * @date 2025年12月28日
 */
@Slf4j
@Component
public class ApiTokenAuthenticationInterceptor implements HandlerInterceptor {

    public static final String[] EXCLUDE_URLS = {
//            "/v2/login",
//            "/v2/sms/**",
//            "/v2/wechat/auth/login",
//            "/v2/nls/getCredentials",
//            "/v2/file/getUploadCredentials",
            "/v2/stock-abnormal-record/get",
//            "/v2/wechat/scan/createQrcode"
    };


    private final PermissionService permissionService;

    private static final PathMatcher pathMatcher = new AntPathMatcher();

    private final JwtUtil jwtUtil;

    private final UserMapper userMapper;

    @Autowired
    public ApiTokenAuthenticationInterceptor(PermissionService permissionService, JwtUtil jwtUtil, UserMapper userMapper) {
        this.permissionService = permissionService;
        this.jwtUtil = jwtUtil;
        this.userMapper = userMapper;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, @NotNull Object handler) throws IOException {
        try {
            // 1、获取请求的URI
            String requestURI = request.getRequestURI();
            // 2、排除不需要认证的URL
            for (String pattern : EXCLUDE_URLS) {
                if (pathMatcher.match(pattern, requestURI)) {
                    return true;
                }
            }
            // 3、暂定不是v2开头的都放行
            if (!requestURI.startsWith("/v2/")) {
                return true;
            }

            // 4、检查是否标记为不需要登录
            if (handler instanceof HandlerMethod handlerHandler) {
                // 检查方法级别的 @NoLoginRequired 注解
                NoLoginRequired noLoginRequired = handlerHandler.getMethodAnnotation(NoLoginRequired.class);
                if (noLoginRequired != null) {
                    log.debug("接口 {} 标记为不需要登录，直接放行。备注：{}", requestURI, noLoginRequired.value());
                    return true;
                }

                // 检查类级别的 @NoLoginRequired 注解
                NoLoginRequired classNoLoginRequired = handlerHandler.getBeanType().getAnnotation(NoLoginRequired.class);
                if (classNoLoginRequired != null) {
                    log.debug("控制器类 {} 标记为不需要登录，直接放行。备注：{}", handlerHandler.getBeanType().getSimpleName(), classNoLoginRequired.value());
                    return true;
                }
            }

            // 5、检查是否有token
            String accessToken = request.getHeader("token");
            if (!StringUtils.hasText(accessToken)) {
                sendErrorResponse(response, WitmoreErrorCode.UNAUTHORIZED);
                return false;
            }
            String claimsStr;
            try {
                claimsStr = jwtUtil.validateToken(accessToken);
                if (!StringUtils.hasText(claimsStr)) {
                    sendErrorResponse(response, WitmoreErrorCode.UNAUTHORIZED);
                    return false;
                }
            } catch (Exception e) {
                sendErrorResponse(response, WitmoreErrorCode.UNAUTHORIZED);
                return false;
            }
            UserSession accountSession = JSONObject.parseObject(claimsStr, UserSession.class);
            if (accountSession == null || accountSession.getId() == null) {
                sendErrorResponse(response, WitmoreErrorCode.UNAUTHORIZED);
                return false;
            }

            UserDO userDO = userMapper.selectById(accountSession.getId());
            if (userDO == null) {
                sendErrorResponse(response, WitmoreErrorCode.UNAUTHORIZED);
                return false;
            }
            // 用户是否被禁用
            if (userDO.getActiveStatus() != null && userDO.getActiveStatus() == 0) {
                sendErrorResponse(response, HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION, WitmoreErrorCode.USER_DISABLE_ERROR.getMessage());
                return false;
            }
            // 超管权限最最最最最最大
            if (userDO.getIsSuperAdmin() != null && !userDO.getIsSuperAdmin()) {
                // 6、权限校验
                List<String> permissionCodes = permissionService.getPermissionNamesByUserId(accountSession.getId().longValue());
                if (handler instanceof HandlerMethod handlerHandler) {
                    RequiresPermission methodAnnotation = handlerHandler.getMethodAnnotation(RequiresPermission.class);
                    if (methodAnnotation != null) {
                        String requestPermissionStr = methodAnnotation.value();
                        // 权限校验
                        if (CollectionUtils.isEmpty(permissionCodes) || !permissionCodes.contains(requestPermissionStr)) {
                            sendErrorResponse(response, HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION, WitmoreErrorCode.NO_AUTH.getMessage());
                            return false;
                        }
                    }
                }
            }

            // 7、设置用户会话信息到ThreadLocal
            GlobalAccountSession.setUserInfo(accountSession);
            return true;
        } catch (Exception e) {
            sendErrorResponse(response, e);
        }
        return false;

    }

    private void sendErrorResponse(HttpServletResponse response, WitmoreErrorCode errorCode) throws IOException {
        sendErrorResponse(response, errorCode.getCode(), errorCode.getMessage());
    }


    private void sendErrorResponse(HttpServletResponse response, Exception e) throws IOException {
        int code = WitmoreErrorCode.SYSTEM_ERROR.getCode();
        String message = e != null ? e.getMessage() : WitmoreErrorCode.SYSTEM_ERROR.getMessage();
        if (e instanceof WitmoreException) {
            WitmoreErrorCode errorCode = ((WitmoreException) e).getErrorCode();
            code = errorCode.getCode();
            message = errorCode.getMessage();
        }
        sendErrorResponse(response, code, message);
    }

    /**
     * 发送错误响应的统一方法，带错误信息
     */
    private void sendErrorResponse(HttpServletResponse response, int errorCode, String errorMessage) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(errorCode);
        // 构建统一的错误响应体
        ResponseResult<Void> responseResult = new ResponseResult<>();
        responseResult.setCode(errorCode);
        responseResult.setMessage(errorMessage);
        responseResult.setData(null);
        // 将错误响应体写入响应流
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.writeValue(response.getWriter(), responseResult);
//        asyncWeChatNotifier.sendSystemErrorToWeChatAsync(errorMessage);
    }


}
